﻿using System.Windows;
using ff14bot.Enums;
using ff14bot.Managers;
using TreeSharp;
using Magitek.Helpers;
using ff14bot;
using System.Windows.Forms;
using Action = TreeSharp.Action;
using ff14bot.Objects;
using ff14bot.Behavior;

namespace Magitek.Rotations
{
    public class BlackMage : Magitek
    {
        public override float PullRange { get { return WindowSettings.BlackMagePullRange; } }
        public override ClassJobType[] Class { get { return new ClassJobType[] { ClassJobType.BlackMage }; } }

        #region Pulling & Resting
        protected override Composite CreatePull()
        {
            return Combat.CreatePull(25);
        }
        protected override Composite CreateRest()
        {
            return Extensions.DefaultRestBehavior(r => Core.Player.CurrentManaPercent);
        }
        #endregion
        #region Buffs // Mainly used for Grindbot etc...

        protected override Composite CreatePreCombatBuffs()
        {
            return new PrioritySelector(
                Extensions.SummonChocobo()
                );
        }

        protected override Composite CreateCombatBuffs()
        {
            return new PrioritySelector(
                Casting.Cast(r => "Manaward", r => Core.Player.CurrentHealthPercent <= WindowSettings.BlackMageUseManawardHp, r => Core.Player, r => 2, r => false),
                Casting.Cast(r => "Manawall", r => Core.Player.CurrentHealthPercent <= WindowSettings.BlackMageUseManaWallHp, r => Core.Player, r => 2, r => false),
                Casting.Cast(r => "Physick", r => Core.Player.CurrentHealthPercent <= WindowSettings.BlackMagePhysickHp && Core.Player.CurrentManaPercent <= WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player, r => 2, r => false),

                //   Raging Strikes if we have Astral Fire III and we have enough mana that we're not wasting it.
                Casting.Cast(r => "Raging Strikes", r => WindowSettings.BlackMageUseRagingStrikes && Core.Player.HasAura(175) && Core.Player.CurrentManaPercent > 60, r => Core.Player, r => 2, r => false),

                //   Quelling Strikes if we have Astral Fire III and we have enough mana that we're not wasting it.
                Casting.Cast(r => "Quelling Strikes", r => WindowSettings.BlackMageUseQuellingStrikes && Core.Player.HasAura(175) && Core.Player.CurrentManaPercent > 60, r => Core.Player, r => 2, r => false),

                //   Virus if we have Astral Fire III and we have enough mana that we're not wasting it.
                Casting.Cast(r => "Virus", r => WindowSettings.BlackMageUseVirus && Core.Player.HasAura(175) && Core.Player.CurrentManaPercent > 60, r => Core.Player.CurrentTarget, r => 2, r => false),

                //   Surecast is there's a mob within our range targeting us.
                Casting.Cast(r => "Surecast", r => WindowSettings.BlackMageUseSurecast && (Core.Player.CurrentTarget as BattleCharacter).CurrentTargetId == Core.Player.ObjectId && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 6 && WindowSettings.BlackMageUseSurecast, r => Core.Player, r => 2, r => false));
        }
        #endregion
        #region Combat
        protected override Composite CreateHeal()
        {
            return new PrioritySelector();
        }

        public override Composite OnTreeSharpPulse()
        {
            return new PrioritySelector(
                new Decorator(r => !Core.Player.InCombat && HasAnyAstral && Core.Player.CurrentManaPercent < WindowSettings.RestEnergy,
                    Casting.Cast(r => "Transpose", r => true, r => Core.Player, r => 2, r => false)));
        }

        protected override Composite CreateCombat()
        {
            return new PrioritySelector(ctx => Core.Player.CurrentTarget,
                new Decorator(ctx => ctx != null,
                new PrioritySelector(
                new Decorator(ctx => ctx != null && BotManager.Current.IsAutonomous,
                    new PrioritySelector(
                        CommonBehaviors.MoveToLos(ctx => ctx as GameObject),
                        CommonBehaviors.MoveAndStop(ctx => (ctx as GameObject).Location, ctx => 20 + (ctx as GameObject).CombatReach, true, "Moving to unit")
						)
					),

                Combat.DoPVP(),

                SingleTargetRotation     
     
            )));
        }

        public Composite SingleTargetRotation
        {
            get
            {
                return new PrioritySelector(
                    new Decorator(r => Core.Player.IsCasting, new ActionAlwaysSucceed()),

                    Transpose,
                    Flare,
                    Procs,
                    Sleep,
                    Blizzard,
                    Thunder,
                    Fire
                    
                    );
            }
        }

        #region BlackMage Spells
        public Composite Blizzard
        {
            get
            {
                return new PrioritySelector(
                    //   Blizzard II AOE if we need to and the setting is enabled.
                    Casting.Cast(r => "Blizzard II", r => WindowSettings.BlackMageUseAOE && WindowSettings.BlackMageUseBlizzard2 && Extensions.EnemiesNearPlayer(5) > WindowSettings.TargetsToAOE && !WindowSettings._dontaoeList.Contains(Core.Player.CurrentTarget.Name), r => Core.Player, r => 2, r => false),

                    //  Blizzard III if we have less mana than our setting and WE DON'T have Umbral.
                    Casting.Cast(r => "Blizzard III", r => WindowSettings.lastspellused != "Swiftcast" && Core.Player.CurrentManaPercent <= WindowSettings.BlackMageBlizzardIIIMana && !HasAnyUmbral, r => Core.Player.CurrentTarget, r => 3, r => true),
                    //   If we have Blizzard III then we can use Blizzard only in certain situations.
                    Casting.Cast(r => "Blizzard", r => WindowSettings.lastspellused != "Swiftcast" && !Actionmanager.CanCast("Convert", Core.Player) && Core.Player.CurrentMana > 0 && Core.Player.CurrentMana < 79 && !HasAnyUmbral, r => Core.Player.CurrentTarget, r => 2, r => false),                    
                    
                    new Decorator(r => Core.Player.ClassLevel < 38, 
                          new PrioritySelector(
                          //   Blizzard we have no Astral or Umbral (we must have just used Blizzard when we had Astral), then keep using it till we're at least 80% mana.
                          Casting.Cast(r => "Blizzard", r => (HasAnyUmbral && Core.Player.CurrentManaPercent < 80) || (!HasAnyUmbral && !HasAnyAstral && Core.Player.CurrentManaPercent < 80), r => Core.Player.CurrentTarget, r => 2, r => false),
                  
                          //   Blizzard if we drop below specified mana, we should then Blizzard again to get Umbral Ice
                          Casting.Cast(r => "Blizzard", r => Core.Player.CurrentManaPercent < WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player.CurrentTarget, r => 2, r => false))));
            }
        }

        public Composite Thunder
        {
            get
            {
                return new PrioritySelector(
                    //   Thunder III as opener on high HP targets.
                    Casting.Cast(r => "Thunder III", r => !HasAnyUmbral && !HasAnyAstral && Core.Player.CurrentManaPercent >= WindowSettings.BlackMageBlizzardIIIMana && !Core.Player.CurrentTarget.HasAura("Thunder", true, 3000) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth > WindowSettings.BlackMageUseThunderAboveHp, r => Core.Player.CurrentTarget, r => 2, r => true),
                    
                    //   Thunder II as open on high HP targets (Lv<46).
                    Casting.Cast(r => "Thunder II", r => !HasAnyUmbral && !HasAnyAstral && Core.Player.ClassLevel < 46 && Core.Player.CurrentManaPercent >= WindowSettings.BlackMageBlizzardIIIMana && !Core.Player.CurrentTarget.HasAura("Thunder", true, 3000) && (Core.Player.CurrentTarget as BattleCharacter).CurrentHealth > WindowSettings.BlackMageUseThunderAboveHp, r => Core.Player.CurrentTarget, r => 3, r => true),

                    //   Thunder as filler during the Umbral Ice phase.
                    Casting.Cast(r => "Thunder", r => !Core.Player.HasAura("Thundercloud") && WindowSettings.lastspellused == "Blizzard III", r => Core.Player.CurrentTarget, r => 2, r => true),
                    
                    //   Otherwise Scathe as filler during the Umbral Ice phase after Thunder (or Thunder III from Thundercloud Proc).
                    Casting.Cast(r => "Scathe", r => (WindowSettings.lastspellused == "Thunder" || WindowSettings.lastspellused == "Thunder III") && HasAnyUmbral, r => Core.Player.CurrentTarget, r => 2, r => true));

            }
        }

        public Composite Flare
        {
            get
            {
                return new PrioritySelector(             
                    //   Swiftcast if Single Target Flare is enabled and we have LESS MANA than we set for Blizzard III but enough mana to cast Flare. 
                    Casting.Cast(r => "Swiftcast", r => WindowSettings.BlackMageUseSingleFlare && Core.Player.CurrentManaPercent < WindowSettings.BlackMageBlizzardIIIMana && Core.Player.CurrentMana > 270 && Actionmanager.CanCast("Convert", Core.Player), r => Core.Player, r => 4, r => false),

                    //   Otherwise Use Swiftcast for AoE Flare if we have LESS MANA than we set for Blizzard III but enough mana to cast Flare. 
                    Casting.Cast(r => "Swiftcast", r => !WindowSettings.BlackMageUseSingleFlare && WindowSettings.BlackMageUseAOE && Extensions.EnemiesNearTarget(5) >= WindowSettings.TargetsToAOE && Core.Player.CurrentManaPercent < WindowSettings.BlackMageBlizzardIIIMana && Core.Player.CurrentMana > 270 && Actionmanager.CanCast("Convert", Core.Player), r => Core.Player, r => 4, r => false),

                    //   Flare if we have Swiftcast and Convert and either Single Target Flare is enabled or an AoE situation is present.
                    Casting.Cast(r => "Flare", r => (WindowSettings.BlackMageUseSingleFlare || WindowSettings.BlackMageUseAOE && Extensions.EnemiesNearTarget(5) >= WindowSettings.TargetsToAOE) && WindowSettings.lastspellused == "Swiftcast" && Actionmanager.CanCast("Convert", Core.Player), r => Core.Player.CurrentTarget, r => 2, r => false),

                    //   Convert if we are low on mana, which means we either just used Flare or messed up our rotation (by possibly setting the BlackMageBlizzardIIIMana setting too low).
                    Casting.Cast(r => "Convert", r => Core.Player.CurrentMana < 79 && !HasAnyUmbral, r => Core.Player, r => 2, r => false));
            }
        }

        public Composite Transpose
        {
            get
            {
                return new PrioritySelector(
                    //   Transpose at the end of the Umbral Ice phase if I get a Firestarter proc during the Blizzard III cast so that Fire III can do more damage.
                    Casting.Cast(r => "Transpose", r => Core.Player.HasAura("Umbral Ice III") && Core.Player.HasAura("Firestarter") && Core.Player.CurrentManaPercent == 100, r => Core.Player, r => 3, r => false),

                    //   If we're below 38 it means we don't have Blizzard III, we need to Transpose when we get below our setting.
                    new Decorator(r => Core.Player.ClassLevel < 38, new PrioritySelector(
                    Casting.Cast(r => "Transpose", r => HasAnyAstral && Core.Player.CurrentManaPercent < WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player, r => 2, r => false))));
            }
        }

        public Composite Fire
        {
            get
            {
                return new PrioritySelector(
                    Casting.Cast(r => "Fire III", r => !Core.Player.HasAura("Firestarter") && ((Core.Player.ClassLevel >= 40 && !Core.Player.HasAura("Astral Fire III")) || (Core.Player.ClassLevel >= 34 && Core.Player.ClassLevel < 40 && !Core.Player.HasAura("Astral Fire II"))) && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player.CurrentTarget, r => 3, r => true),

                    //   Swiftcast for Fire and Fire II if Convert for Flare is down. 
                    Casting.Cast(r => "Swiftcast", r => !Actionmanager.CanCast("Convert", Core.Player) && HasAnyAstral && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player, r => 4, r => false),

                    Casting.Cast(r => "Fire II", r => WindowSettings.BlackMageUseAOE && Extensions.EnemiesNearTarget(5) >= WindowSettings.TargetsToAOE && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana && ((Core.Player.ClassLevel >= 40 && Core.Player.HasAura("Astral Fire III")) || (Core.Player.ClassLevel >= 34 && Core.Player.ClassLevel < 40 && Core.Player.HasAura("Astral Fire II"))), r => Core.Player.CurrentTarget, r => 2, r => false),

                    //   Swiftcast for Fire/Fire II if never using Flare (needed as Convert will be up unless AoE situation appears). 
                    Casting.Cast(r => "Swiftcast", r => !WindowSettings.BlackMageUseSingleFlare && HasAnyAstral && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana, r => Core.Player, r => 4, r => false),

                    Casting.Cast(r => "Fire", r => Core.Player.ClassLevel <= 34 && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana || HasAnyAstral && Core.Player.CurrentManaPercent > WindowSettings.BlackMageBlizzardIIIMana && !Extensions.DoubleCastPreventionDict.Contains(Core.Player.CurrentTarget, "Blizzard III"), r => Core.Player.CurrentTarget, r => 2, r => false),
                                        
                    //   Scathe if moving.
                    Casting.Cast(r => "Scathe", r => MovementManager.IsMoving && Core.Player.CurrentMana > 743, r => Core.Player.CurrentTarget, r => 2, r => true));
            }
        }

        public Composite Procs
        {
            get
            {
                return new Decorator(r => Core.Player.HasAura("Thundercloud") || Core.Player.HasAura("Firestarter"), new PrioritySelector(
                    Casting.Cast(r => "Fire III", r => WindowSettings.lastspellused != "Swiftcast" && WindowSettings.lastspellused != "Blizzard III" && Core.Player.HasAura("Firestarter") && !HasAnyUmbral, r => Core.Player.CurrentTarget, r => 3, r => true),
                    Casting.Cast(r => "Fire III", r => WindowSettings.lastspellused != "Swiftcast" && WindowSettings.lastspellused != "Blizzard III" && Core.Player.HasAura("Firestarter") && HasAnyUmbral && WindowSettings.lastspellused == "Transpose", r => Core.Player.CurrentTarget, r => 3, r => true),
                    Casting.Cast(r => "Thunder III", r => WindowSettings.lastspellused != "Swiftcast" && Core.Player.HasAura("Thundercloud"), r => Core.Player.CurrentTarget, r => 2, r => false),
                    Casting.Cast(r => "Thunder II", r => Core.Player.ClassLevel < 46 && Core.Player.HasAura("Thundercloud"), r => Core.Player.CurrentTarget, r => 2, r => false)));
            }
        }

        public Composite Sleep
        {
            get
            {
                return Casting.Cast(r => "Sleep", r => KeyboardPolling.IsKeyDown(Keys.LShiftKey), r => Core.Player.CurrentTarget, r => 2, r => false);
            }
        }

        public bool HasAnyUmbral
        {
            get { return Core.Player.HasAura("Umbral Ice") || Core.Player.HasAura("Umbral Ice II") || Core.Player.HasAura("Umbral Ice III"); } 
        }

        public bool HasAnyAstral
        {
            get { return Core.Player.HasAura("Astral Fire") || Core.Player.HasAura("Astral Fire II") || Core.Player.HasAura("Astral Fire III"); }
        }
        #endregion

        #endregion
    }
}
